#pragma once

#include <iostream>
#include <string>
#include <jsoncpp/json/json.h>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <sys/socket.h>
#include "Util.hpp"

namespace ns_protocol
{

// 定制协议
#define SEP " "                           // 定义分隔符
#define SEP_LEN strlen(SEP)               // 分隔符长度
#define HEADER_SEP "\r\n"                 // 报头分隔符
#define HEADER_SEP_LEN strlen(HEADER_SEP) // 报头分隔符长度
                                          // #define USER 1

    enum
    {
        READ_ERR = -1,
        READ_KEEP,
    };

    std::string AddHeader(const std::string &str)
    {
        // 添加报头
        std::string packageStr = std::to_string(str.size());
        packageStr += HEADER_SEP;
        packageStr += str;
        packageStr += HEADER_SEP;

        std::cout << "报头添加完成 packageStr" << endl
                  << packageStr;

        return packageStr;
    }

    std::string RemoveHeader(const std::string &package, int len)
    {
        // 移除报头 -> 获取有效载荷
        return package.substr(package.size() - HEADER_SEP_LEN - len, len);
    }

    int ParsePackage(std::string &inbuff, std::string *package)
    {
        // 检测阶段
        int pos = inbuff.find(HEADER_SEP);
        if (pos == std::string::npos)
            return READ_KEEP; // 显然没有读到完整的报文，重新读

        std::string lenStr = inbuff.substr(0, pos);                                             // 合法子串: 5\r\n
        int targetEndPos = lenStr.size() + Yohifo::Util::StrToInt(lenStr) + 2 * HEADER_SEP_LEN; // 报头长度 + 有效载荷长度 + 2个分隔符长度

        // 如果当前报文结束的位置不对，那说明没有读完
        if (targetEndPos < inbuff.size())
            return READ_KEEP;

        // 成功获取到一个完整的报文
        *package = inbuff.substr(0, targetEndPos);
        inbuff.erase(0, targetEndPos);

        return Yohifo::Util::StrToInt(lenStr); // 返回有效载荷的长度
    }

    // 请求（传入操作数与运算符）
    class Request
    {
    public:
        Request()
        {
        }

        Request(int x, char op, int y)
            : _x(x), _op(op), _y(y)
        {
        }

        // 序列化格式：_x _op _y
        void Serialize(std::string *outStr)
        {
#ifdef USER
            // 将序列化后的数据写入 outStr 中
            *outStr += std::to_string(_x);
            *outStr += SEP;
            *outStr += _op;
            *outStr += SEP;
            *outStr += std::to_string(_y);
#else
            // 使用 Json
            Json::Value root;
            root["x"] = _x;
            root["op"] = _op;
            root["y"] = _y;

            Json::FastWriter writer;
            *outStr = writer.write(root);
#endif

            std::cout << "序列化完成 *outStr:" << *outStr << endl;
        }

        // 反序列化
        void Deserialize(const std::string &inStr)
        {
#ifdef USER
            // 将数据分割后，放入字符串数组中
            std::vector<std::string> result;
            Util::StringSplit(inStr, SEP, SEP_LEN, result);

            // x -> result[0]
            // op -> result[1]
            // y -> result[2]

            _x = Util::StrToInt(result[0]);
            _op = result[1][0]; // 运算符为单个字符
            _y = Util::StrToInt(result[2]);
#else
            // 使用Json
            Json::Value root;
            Json::Reader reader;
            reader.parse(inStr, root);

            _x = root["x"].asInt();
            _op = root["op"].asInt();
            _y = root["y"].asInt();
#endif
            std::cout << "反序列化完成 _x _op _y:" << _x << " " << _op << " " << _y << std::endl;
        }

        int getX() const { return _x; }
        char getOP() const { return _op; }
        int getY() const { return _y; }

    private:
        int _x;
        char _op;
        int _y;
    };

    // 回复（传入结果与错误码）
    class Response
    {
    public:
        Response()
        {
        }

        Response(int ret, int cod)
            : _result(ret), _code(cod)
        {
        }

        void Serialize(string *outStr)
        {
#ifdef USER
            *outStr += std::to_string(_result);
            *outStr += SEP;
            *outStr += std::to_string(_code);
#else
            // 使用 Json
            Json::Value root;
            root["result"] = _result;
            root["code"] = _code;

            // Json::FastWriter writer;
            Json::StyledWriter writer;
            *outStr = writer.write(root);
#endif
            std::cout << "序列化完成 *outStr:" << *outStr << endl;
        }

        // 反序列化
        void Deserialize(const std::string &inStr)
        {
#ifdef USER
            // 将数据分割后，放入字符串数组中
            std::vector<std::string> result;
            Util::StringSplit(inStr, SEP, SEP_LEN, result);

            // ret -> result[0]
            // code -> result[1]

            _result = Util::StrToInt(result[0]);
            _code = Util::StrToInt(result[1]);
#else
            // 使用Json
            Json::Value root;
            Json::Reader reader;
            reader.parse(inStr, root);

            _result = root["result"].asInt();
            _code = root["code"].asInt();
#endif
            std::cout << "反序列化完成 _result _code:" << _result << " " << _code << std::endl;
        }

        int getRet() const { return _result; }
        int getCode() const { return _code; }

    private:
        int _result;
        int _code;
    };
}